package AI;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

import org.newdawn.slick.geom.Vector2f;

import constans.Globals;
import controller.ObjectController;
import engine.MapMatrix;
import entity.Entity;

public class Path {


	private Vector2f start;
	private Vector2f target;
	private LinkedList<Vector2f> path = new LinkedList<Vector2f>();
	private MapMatrix tab;
	private int[][] map; 
	private boolean isPath;
	
	private boolean isTarget = false;
	
	public Path(Vector2f start, Vector2f target)
	{
		this.start = start;
		this.target = target;
		setMap();	
		prepareMap();
	}
	private void setMap()
	{
		tab = ObjectController.getMap();
		map = new int[Globals.MAP_I][Globals.MAP_J];
		
		for(int i = 0; i < Globals.MAP_I ; i++)
			for(int j = 0; j < Globals.MAP_J ; j++)			
				if(tab.getEntity(i, j) != null)
					if(tab.getEntity(i, j).getType() == Entity.BUILDING)
						map[i][j] = -1;
					else map[i][j] = 0;
	}	
	private void prepareMap()
	{
		LinkedList<Vector2f> queue = new LinkedList<Vector2f>();
        queue.addFirst(start);
        map[(int) start.x][(int) start.y] = 1;
        makingMap : while(true)
        {
        	//nie ma sciezki
        	if(queue.isEmpty())
        	{
        		isPath = false;
            	return;
        	}
        	Vector2f tmp = queue.getLast();
            queue.removeLast();
            for(int i = -1; i <= 1 ; i++)
            	for(int j = -1; j <= 1 ; j++)       
            	{       
            		int i1 = (int)(tmp.x)+i;
            		int j1 = (int)(tmp.y)+j;
            		if(i1 >= 0 && i1 < Globals.MAP_I && j1 >= 0 && j1 < Globals.MAP_J)                                              
            			if(map[i1][j1] == 0) 
            			{    
            				if(i*i != j*j)
            				{
            					map[i1][j1] = map[(int) tmp.x][(int) tmp.y] + 1;
            					if(i1 == target.x  && j1 == target.y) break makingMap;
                    			queue.addFirst(new Vector2f(i1, j1));
            				}
            				else
            					if(map[i1][(int) tmp.y] >= 0 && map[(int) tmp.x][j1] >= 0)
            					{
            						map[i1][j1] = map[(int) tmp.x][(int) tmp.y] + 1;
            						if(i1 == target.x  && j1 == target.y) break makingMap;
                    				queue.addFirst(new Vector2f(i1, j1));
            					}             				   					
            			}
            	}   
        }   	     	
		isPath = true;
		findPath();		  	
	}
	private void findPath()
	{
		Vector2f tmp = target;
	  	path.addFirst(tmp);
		search : while(true)
	  	{
	  		LinkedList<Vector2f> q = new LinkedList<Vector2f>();
	  		for(int i = -1; i <= 1 ; i++)
	  		{
	  			for(int j = -1; j <= 1 ; j++)
	  			{    					
	  				int i1 = (int)(tmp.x)+i;
	  				int j1 = (int)(tmp.y)+j;
	  				
	  				
	  				if(i1 >= 0 && i1 < Globals.MAP_I && j1 >= 0 && j1 < Globals.MAP_J)
	  				{   
	  					if(i*i != j*j)
	  						q.addFirst(new Vector2f(i1,j1));
	  					else
	  						q.addLast(new Vector2f(i1,j1));
	  				}
	  			}
	  			
	  		}
	  		searchingNextPoint : while(true)
	  		{
	  			Vector2f t = q.getFirst();
	  			q.removeFirst();
	  			int val = map[(int)t.x][(int)t.y] + 1;
	  			if(val == map[(int) tmp.x][(int) tmp.y]) 
	  			{
	  				if(t.x == start.x && t.y == start.y) break search;
	  				path.addFirst(t);
	  				break searchingNextPoint;
	  			}  
	  		}			
	  	tmp = path.getFirst();
	  	}
	}
	private void writeMap()
	{
		for(int i = 0; i < Globals.MAP_I ; i++)
		{
			for(int j = 0; j < Globals.MAP_J ; j++)
				System.out.print(map[i][j]+" ");
			System.out.println();
		}
		System.out.println("-------------------------------------------------------");
	}
	public LinkedList getPath()
	{
		return path;
	}
	public boolean isPath()
	{
		return isPath;
	}
}
